home *** CD-ROM | disk | FTP | other *** search
Wrap
/* File: ext2.c Copyright (C) 1998-2004 Christophe GRENIER <grenier@cgsecurity.org> This software is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdio.h> #include <string.h> #include "types.h" #include "common.h" #include "ext2.h" #include "intrface.h" #include "fnctdsk.h" #define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size) static int test_EXT2(t_param_disk *disk_car, const struct ext2_super_block *sb,t_diskext *partition,const int debug, const int dump_ind); int check_EXT2(t_param_disk *disk_car,t_diskext *partition,const int debug) { unsigned char buffer[8*SECTOR_SIZE]; if(disk_car->read(disk_car,8, &buffer, partition->lba)!=0) { return 1; } if(test_EXT2(disk_car,(struct ext2_super_block*)&buffer[0x400],partition,debug,0)!=0) return 1; set_EXT2_info(disk_car,(struct ext2_super_block*)&buffer[0x400],partition,debug,0); return 0; } int set_EXT2_info(t_param_disk *disk_car, const struct ext2_super_block *sb,t_diskext *partition,const int debug, const int dump_ind) { partition->info[0]='\0'; set_part_name(partition,sb->s_volume_name,16); /* sb->s_last_mounted seems to be unemployed in kernel 2.2.16 */ if(EXT2_HAS_COMPAT_FEATURE(sb,EXT3_FEATURE_COMPAT_HAS_JOURNAL)!=0) strncpy(partition->info,"EXT3 ",sizeof(partition->info)); else strncpy(partition->info,"EXT2 ",sizeof(partition->info)); if(EXT2_HAS_RO_COMPAT_FEATURE(sb,EXT2_FEATURE_RO_COMPAT_LARGE_FILE)!=0) strcat(partition->info,"Large file "); if(EXT2_HAS_RO_COMPAT_FEATURE(sb,EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)!=0) strcat(partition->info,"Sparse superblock "); if(EXT2_HAS_INCOMPAT_FEATURE(sb,EXT3_FEATURE_INCOMPAT_RECOVER)!=0) strcat(partition->info,"Recover "); if(EXT2_HAS_INCOMPAT_FEATURE(sb,EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)!=0) strcat(partition->info,"Journal dev "); if(le16(sb->s_block_group_nr)!=0) { strcat(partition->info,"Backup superblock "); if(debug!=0) { ecrit_rapport("\nblock_group_nr %u\n",le16(sb->s_block_group_nr)); } } /* last mounted => date */ return 0; } /* Primary superblock is at 1024 (SUPERBLOCK_OFFSET) Group 0 begin at s_first_data_block */ int recover_EXT2(t_param_disk *disk_car, const struct ext2_super_block *sb,t_diskext *partition,const int debug, const int dump_ind) { if(test_EXT2(disk_car,sb,partition,debug,dump_ind)!=0) return 1; set_EXT2_info(disk_car,sb,partition,debug,dump_ind); partition->part_type=(unsigned char)P_LINUX; partition->part_size=le32(sb->s_blocks_count)*(EXT2_MIN_BLOCK<<le32(sb->s_log_block_size)); partition->boot_sector=le16(sb->s_block_group_nr)*le32(sb->s_blocks_per_group); partition->boot_sector=0; partition->blocksize=EXT2_MIN_BLOCK_SIZE<<le32(sb->s_log_block_size); if(le16(sb->s_block_group_nr)>0) { partition->lba-=(le32(sb->s_first_data_block)+le16(sb->s_block_group_nr)*le32(sb->s_blocks_per_group))*(EXT2_MIN_BLOCK<<le32(sb->s_log_block_size)); } if(debug!=0) { ecrit_rapport("\nrecover_EXT2: s_block_group_nr=%u/%u, s_mnt_count=%u/%d, s_blocks_per_group=%u\n", le16(sb->s_block_group_nr), le32(sb->s_blocks_count)/le32(sb->s_blocks_per_group), le16(sb->s_mnt_count),le16(sb->s_max_mnt_count),le32(sb->s_blocks_per_group)); ecrit_rapport("recover_EXT2: boot_sector=%lu, s_blocksize=%lu\n",partition->boot_sector,partition->blocksize); ecrit_rapport("recover_EXT2: s_blocks_count %u\n",le32(sb->s_blocks_count)); ecrit_rapport("recover_EXT2: part_size %lu\n",partition->part_size); /* { unsigned char buffer2[2*SECTOR_SIZE]; unsigned int group; group=1; while(group<=9) { dword hd_offset=partition->lba+(le32(sb->s_first_data_block)+group*le32(sb->s_blocks_per_group))*(EXT2_MIN_BLOCK<<le32(sb->s_log_block_size)); ecrit_rapport("%lu+(%u+%u*%u)*%u\n",partition->lba,le32(sb->s_first_data_block),group,le32(sb->s_blocks_per_group),(EXT2_MIN_BLOCK<<le32(sb->s_log_block_size))); ecrit_rapport("Group %u Backup superblock at %u (LBA=%lu) ",group,group*le32(sb->s_blocks_per_group),hd_offset); if(disk_car->read(disk_car,2, buffer2, hd_offset)==0) { const struct ext2_super_block *sb2=(const struct ext2_super_block*)&buffer2; unsigned int res=test_EXT2(disk_car,sb2,partition,debug,dump_ind); if(res==0) { ecrit_rapport("Ok\n"); } else { ecrit_rapport("Bad res=%u\n",res); } // dump(stdscr,buffer2,2*SECTOR_SIZE); } if(group==0) group=1; else if(group==1) group=3; else if(group==3) group=5; else if(group==5) group=7; else if(group==7) group=9; else group=11; } } */ } return 0; } static int test_EXT2(t_param_disk *disk_car, const struct ext2_super_block *sb,t_diskext *partition,const int debug, const int dump_ind) { if(le16(sb->s_magic)!=EXT2_SUPER_MAGIC) return 1; if(dump_ind!=0) { ecrit_rapport("\nLinux magic value at %u/%u/%u\n", LBA2cylinder(disk_car,partition->lba),LBA2head(disk_car,partition->lba),LBA2sector(disk_car,partition->lba)); /* There is a little offset ... */ dump(stdscr,sb,SECTOR_SIZE); } if (le32(sb->s_free_blocks_count) >= le32(sb->s_blocks_count)) return 2; if (le32(sb->s_free_inodes_count) >= le32(sb->s_inodes_count)) return 3; if (le16(sb->s_errors)!=0 && (le16(sb->s_errors) != EXT2_ERRORS_CONTINUE) && (le16(sb->s_errors) != EXT2_ERRORS_RO) && (le16(sb->s_errors) != EXT2_ERRORS_PANIC)) return 5; if ((le16(sb->s_state) & ~(EXT2_VALID_FS | EXT2_ERROR_FS))!=0) return 5; if (le32(sb->s_blocks_count) == 0) /* reject empty filesystem */ return 6; if(le32(sb->s_log_block_size)>2) /* block size max = 4096, can be 8192 on alpha */ return 7; if(partition->part_size!=0 && (partition->part_size<le32(sb->s_blocks_count)*(EXT2_MIN_BLOCK<<le32(sb->s_log_block_size)))) return 8; if(EXT2_HAS_COMPAT_FEATURE(sb,EXT3_FEATURE_COMPAT_HAS_JOURNAL)!=0) partition->upart_type=UP_EXT3; else partition->upart_type=UP_EXT2; return 0; }